package com.linkoog.devtools.archive.action.zip;


import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.LinkedHashMap;
import java.util.Map;



public class ZipHandler {

    public static void zip(Map<String, Path> archiveFiles, String outputDir, String fileName) throws IOException{
        String targetPath;
        if (outputDir.endsWith("/")){
            targetPath = outputDir + fileName;
        } else {
            targetPath = outputDir + "/" + fileName;
        }

        try (FileOutputStream fos = new FileOutputStream(targetPath);
             ZipArchiveOutputStream zos = new ZipArchiveOutputStream(fos)) {
            for (Map.Entry<String, Path> entry : archiveFiles.entrySet()) {
                String key = entry.getKey();
                Path path = entry.getValue();
                if (Files.isDirectory(path)){
                    ZipArchiveEntry zipEntry = new ZipArchiveEntry(key);
                    zos.putArchiveEntry(zipEntry);
                    zos.closeArchiveEntry();
                } else {
                    ZipArchiveEntry zae = new ZipArchiveEntry(key);
                    zos.putArchiveEntry(zae);
                    Files.copy(path, zos);
                    zos.closeArchiveEntry();
                }
            }
        }
    }

    public static Map<String, Path> handler(String rootName, Path sourceFolderPath) throws IOException {
        String rootDir = handlerRootName(rootName);
        LinkedHashMap<String,Path > map = new LinkedHashMap<>();
        Files.walkFileTree(sourceFolderPath, new SimpleFileVisitor<Path>() {
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                String relativePath = sourceFolderPath.relativize(file).toString();
                if (relativePath.isEmpty()){
                    map.put(rootDir + "/" + file.getFileName(), file);
                    return FileVisitResult.CONTINUE;
                }

                if (relativePath.startsWith("/")){
                    map.put(rootDir + relativePath, file);
                } else {
                    map.put(rootDir + "/" + relativePath, file);
                }
                return FileVisitResult.CONTINUE;
            }

            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                String relativePath = sourceFolderPath.relativize(dir).toString();
                if (relativePath.isEmpty()){
                    map.put(rootDir + "/", dir);
                    return FileVisitResult.CONTINUE;
                }

                if (relativePath.startsWith("/")){
                    map.put(rootDir + relativePath+ "/", dir);
                } else {
                    map.put(rootDir + "/" + relativePath+ "/", dir);
                }
                return FileVisitResult.CONTINUE;
            }
        });
        return map;
    }

    private static String handlerRootName(String rootName){
        if (rootName == null || rootName.trim().isEmpty()) return "";

        rootName = rootName.trim();
        rootName = rootName.replaceAll("/+$", "");
        if (rootName.isEmpty()) return "";

        if (! rootName.startsWith("/") ){
            rootName = "/" + rootName;
        }

        return rootName;
    }
}
